package com.wk.controller;

import com.google.common.eventbus.Subscribe;
import com.wk.common.GlobalConsts;
import com.wk.socket.ClientMessage;
import com.wk.socket.ServerMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageExceptionHandler;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.simp.annotation.SendToUser;
import org.springframework.messaging.simp.annotation.SubscribeMapping;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.web.util.HtmlUtils;

import java.security.Principal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

@Controller
public class WebSocketController
{

    //SimpMessagingTemplate是Spring-WebSocket内置的一个消息发送工具，可以将消息发送到指定的客户端
    private final SimpMessagingTemplate messagingTemplate;

    @Autowired
    public WebSocketController(SimpMessagingTemplate messagingTemplate) {
        this.messagingTemplate = messagingTemplate;
    }

    //接收/app/hello发来的value，然后将value转发到/topic/greetings客户端
    // /topic/greetings是客户端发起连接后，订阅服务端消息时指定的一个地址，用于接收服务端的返回
    @MessageMapping("/hello")
    @SendTo("/topic/greetings")
    public ServerMessage greeting(ClientMessage message) throws Exception
    {
        Thread.sleep(1000);
        System.out.println("请求路径/hello,发送路径/topic/greetings,消息为 " + message.getMessage());
        return new ServerMessage("hello," + HtmlUtils.htmlEscape(message.getMessage()) + "!");
        //注意，这个返回值并不是返回给客户端的，而是转发给消息代理的，
        // 如果客户端想要这个返回值的话，只能从消息代理订阅。
        // @SendTo 注解重写了消息代理的目的地，
        // 如果不指定@SendTo，帧所发往的目的地会与触发处理器方法的目的地相同，只不过会添加上“/topic”前缀。
    }

    @SubscribeMapping("/directReturn")
    public ServerMessage retMessage()
    {
        return new ServerMessage("直接返回");
    }

    /**
     * 定时推送消息
     */
    //@Scheduled(fixedRate = 2000)
    public void callback() {
        // 发现消息
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("推送路径,消息为 " + df.format(new Date()));

        //将给定的对象进行序列化，使用‘MessageConverter’进行包装转化成一条消息，发送到指定的目标
        messagingTemplate.convertAndSend("/topic/callback", "定时推送消息时间: " + df.format(new Date()));
    }

    /*
    * 广播消息，不指定用户，所有订阅的用户都能收到消息
    * 某个用户请求广播地址/app/broadcast触发发送动作，所有订阅了/topic/cast的用户，都会获取到返回值message
    * */
    @MessageMapping("/broadcast")
    public void broadcast(ServerMessage message)
    {
        messagingTemplate.convertAndSend("/topic/cast",message);
    }

    @MessageMapping("/shout")
    @SendToUser("/topic/notifications")
    public ServerMessage userStomp(Principal principal,ServerMessage message)
    {
        String name =  principal.getName();
        String msg = message.getMessage();
        System.out.println("认证的名字是：" + name + "，收到的消息是："+ message);
        return message;
    }

    @MessageMapping("/singleshout")
    public void singleShout(ServerMessage msg, StompHeaderAccessor accessor)
    {
        String message = msg.getMessage();
        System.out.println("收到的消息是："+ message);
        Principal user = accessor.getUser();
        messagingTemplate.convertAndSendToUser(user.getName(),"/topic/shouts",msg);
    }

    @MessageExceptionHandler(Exception.class)
    @SendToUser("/topic/errors")
    public Exception handlerExceptions(Exception t)
    {
        t.printStackTrace();
        return t;
    }

}
